package com.gitee.huanminabc.utils_tools.redis.jedis.config;

import com.gitee.huanminabc.utils_tools.redis.config.RedisAutoConfiguration;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.*;


import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 简要描述
 *
 * @Author: huanmin
 * @Date: 2022/8/4 11:54
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@Configuration
public class JedisConfig {
    @Autowired
    private RedisAutoConfiguration redisAutoConfiguration;

    @Bean
    //单机模式
    public JedisPool singleJedisPool() {
        if (!"single".equals(redisAutoConfiguration.getModel())) {
            return null;
        }
        RedisAutoConfiguration.PoolRedisConfig pool = redisAutoConfiguration.getPool();
        String singleNode = redisAutoConfiguration.getSingleNode();
        RedisAutoConfiguration.NodeRedisConfig nodeConfig = redisAutoConfiguration.getNodeConfig(singleNode);

        GenericObjectPoolConfig<Jedis> jedisPoolConfig = new GenericObjectPoolConfig<>();
        jedisPoolConfig.setMaxIdle(pool.getMaxIdle());
        jedisPoolConfig.setMinIdle(pool.getMinIdle());
        jedisPoolConfig.setMaxTotal(pool.getMaxActive());
        jedisPoolConfig.setMaxWaitMillis(pool.getMaxWait());
        jedisPoolConfig.setJmxEnabled(false);


        JedisPool jedisPool = null;
        if (Strings.isBlank(nodeConfig.getPassword())) {
            jedisPool = new JedisPool(jedisPoolConfig, nodeConfig.getHost(), nodeConfig.getPort(), pool.getTimeout());
        } else {
            jedisPool = new JedisPool(jedisPoolConfig, nodeConfig.getHost(), nodeConfig.getPort(), pool.getTimeout(), nodeConfig.getPassword(), redisAutoConfiguration.getDbIndex());
        }

        return jedisPool;
    }


    @Bean
    //哨兵模式
    public JedisSentinelPool sentinelJedisPool() {
        if (!"sentinel".equals(redisAutoConfiguration.getModel())) {
            return null;
        }
        RedisAutoConfiguration.PoolRedisConfig pool = redisAutoConfiguration.getPool();
        List<Map<String, RedisAutoConfiguration.NodeRedisConfig>> nodes = redisAutoConfiguration.getNodes();
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(pool.getMaxIdle());
        jedisPoolConfig.setMinIdle(pool.getMinIdle());
        jedisPoolConfig.setMaxTotal(pool.getMaxActive());
        jedisPoolConfig.setMaxWaitMillis(pool.getMaxWait());


        String password = ""; //哨兵模式中redis的密码是一样的
        Set<HostAndPort> sentinels = new HashSet<>();
        for (Map<String, RedisAutoConfiguration.NodeRedisConfig> node : nodes) {
            for (Map.Entry<String, RedisAutoConfiguration.NodeRedisConfig> entry : node.entrySet()) {
                RedisAutoConfiguration.NodeRedisConfig nodeConfig = entry.getValue();
                sentinels.add(new HostAndPort(nodeConfig.getHost(), nodeConfig.getPort()));
                if ("".equals(password)) {
                    password = nodeConfig.getPassword();
                } else {
                    if (!password.equals(nodeConfig.getPassword())) {
                        throw new RuntimeException("哨兵模式中redis的密码不一致");
                    }
                }

            }
        }
        JedisSentinelPool jedisSentinelPool = null;
        //因为底层会以:分割,所以这里需要转换为Set
        Set<String> nodesStr = sentinels.stream().map(HostAndPort::toString).collect(Collectors.toSet());
        if (Strings.isNotBlank(password)) {
            jedisSentinelPool=new JedisSentinelPool(redisAutoConfiguration.getSentinelMaster(), nodesStr, jedisPoolConfig, pool.getTimeout(), password);

        }else {
            jedisSentinelPool= new JedisSentinelPool(redisAutoConfiguration.getSentinelMaster(), nodesStr, jedisPoolConfig, pool.getTimeout());
        }

        return jedisSentinelPool;
    }


    @Bean
    //集群模式(只支持0号库,不支持切换库)
    public JedisCluster clusterJedisPool() {
        String model = redisAutoConfiguration.getModel();
        if (!"cluster".equals(model)) {
            return null;
        }
        RedisAutoConfiguration.PoolRedisConfig pool = redisAutoConfiguration.getPool();
        List<Map<String, RedisAutoConfiguration.NodeRedisConfig>> nodes = redisAutoConfiguration.getNodes();

        //集群模式中redis的密码是一样的
        String password = "";
        Set<HostAndPort> clusterNodes = new HashSet<>();
        for (Map<String, RedisAutoConfiguration.NodeRedisConfig> node : nodes) {
            for (Map.Entry<String, RedisAutoConfiguration.NodeRedisConfig> entry : node.entrySet()) {
                RedisAutoConfiguration.NodeRedisConfig nodeConfig = entry.getValue();
                clusterNodes.add(new HostAndPort(nodeConfig.getHost(), nodeConfig.getPort()));
                if ("".equals(password)) {
                    password = nodeConfig.getPassword();
                } else {
                    if (!password.equals(nodeConfig.getPassword())) {
                        throw new RuntimeException("集群模式中redis的密码不一致");
                    }
                }
            }
        }

        GenericObjectPoolConfig<Connection> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxIdle(pool.getMaxIdle());
        poolConfig.setMinIdle(pool.getMinIdle());
        poolConfig.setMaxTotal(pool.getMaxActive());
        poolConfig.setMaxWaitMillis(pool.getMaxWait());
        poolConfig.setJmxEnabled(false);
        JedisCluster jedisCluster = null;
        if (Strings.isNotBlank(password)) {
            jedisCluster = new JedisCluster(clusterNodes, pool.getTimeout(), pool.getTimeout(), 5, password, poolConfig);

        }else{
            //soTimeout 表示读取数据的超时时间,这个写死就行3000
            jedisCluster = new JedisCluster(clusterNodes, pool.getTimeout(), 3000, 5, poolConfig);
        }
        return jedisCluster;
    }


}

